
// 先看一个开胃面试题
// Promise.resolve().then(() => {
//     console.log(0);
//     return Promise.resolve(4);
// }).then((res) => {
//     console.log(res)
// })
// Promise.resolve().then(() => {
//     console.log(1);
// }).then(() => {
//     console.log(2);
// }).then(() => {
//     console.log(3);
// }).then(() => {
//     console.log(5);
// }).then(() =>{
//     console.log(6);
// })

// // 开始尝试分析执行过程
// // script加载主线任务，执行完毕执行微任务，以下为微任务队列伪代码
// () => {
//     console.log(0);
//     return Promise.resolve(4);
// }).then((res) => {
//     console.log(res)
// }
// () => {
//     console.log(1);
// }).then(() => {
//     console.log(2);
// }).then(() => {
//     console.log(3);
// }).then(() => {
//     console.log(5);
// }).then(() =>{
//     console.log(6);
// }
// // 上面打印先打印0，然后把Promise.resolve(4).then(res => console.log(res))放入下一轮微任务，继续往下执行第二个函数，打印1，剩余内容放入下一轮微任务
// Promise.resolve(res => console.log(res))
// () => {
//     console.log(2);
// }).then(() => {
//     console.log(3);
// }).then(() => {
//     console.log(5);
// }).then(() =>{
//     console.log(6);
// }
// // res:4 => console.log(res) 放入下一轮微任务，然后打印2
// res:4 => console.log(res)
// () => {
//     console.log(3);
// }).then(() => {
//     console.log(5);
// }).then(() =>{
//     console.log(6);
// }
// // 依次打印4、3、5、6
// // 分析结果为0 1 2 4 3 5 6
// // 但是打印结果是0 1 2 3 4 5 6，为什么4跑到3的后面去了？

// 既然这样就分析一下Promise A+规范，顺便根据规范实现一个MyPromise
// 1、Promise是一个类，执行这个类的时候传入一个执行器，这个执行器会立即执行
// 2、Promise有三种状态：pending:等待中，fulfilled:完成，reject:失败
// 3、状态只能由pending变为fullfilled或者reject，并且一旦发生改变就不可二次更改
// 4、Promise中使用resolve和reject两个函数来更改状态
// 5、必须有then方法，用来访问最终结果，接收两个参数，一个为成功回调，一个为失败回调，then可以链式调用,可以多次调用
// 根据上面的规范写出第一版Promise
// class MyPromise {
//     status = 'pending'
//     value = undefined
//     reason = undefined
//     constructor(executor) {
//         executor(this.resolve, this.reject)
//     }
//     resolve = (value) => {
//         if (this.status === 'pending') {
//             this.status = 'fulfilled'
//             this.value = value
//         }
//     }
//     reject = (reason) => {
//         if (this.status === 'pending') {
//             this.status = 'reject'
//             this.reason = reason
//         }
//     }
//     then(onFulfilled, onRejected) {
//         if (this.status === 'fulfilled') {
//             onFulfilled(this.value)
//         } else if (this.status === 'reject') {
//             onRejected(this.reason)
//         }
//     }
// }
// 测试一下
// let promise = new MyPromise((res, rej) => {
//     res('成功')
//     rej('失败')
// })
// promise.then((value) => {
//     console.log(value)
// }, (reason) => {
//     console.log(reason)
// })
// 打印成功，符合预期

// 但是这没有处理异步的情况，当创建promise实例的时候传入的函数涉及到异步操作显然是有问题的,如下
// let promise = new MyPromise((res, rej) => {
//     setTimeout(() => {
//         res('成功')
//     }, 100)
// })
// promise.then((value) => {
//     console.log(value)
// })
// 原因：执行.then的时候，Promise的resolve方法还没有执行，status还没有变为fullfilled，所以.then里面不会执行onFulfilled和onRejected，没有结果传出。
// 所以要加一个判断，pending状态的时候，把.then传入的两个回调函数存起来，等状态改变之后再去执行
// 第二版
// class MyPromise {
//     status = 'pending'
//     value = undefined
//     reason = undefined
//     onFulfilledCallback = undefined
//     onRejectedCallback = undefined
//     constructor(executor) {
//         executor(this.resolve, this.reject)
//     }
//     resolve = (value) => {
//         if (this.status === 'pending') {
//             this.status = 'fulfilled'
//             this.value = value
//             this.onFulfilledCallback?.(value)   // resolve后执行存起来的回调函数
//         }
//     }
//     reject = (reason) => {
//         if (this.status === 'pending') {
//             this.status = 'reject'
//             this.reason = reason
//             this.onRejectedCallback?.(reason)   // reject后执行存起来的回调函数
//         }
//     }
//     then(onFulfilled, onRejected) {
//         if (this.status === 'fulfilled') {
//             onFulfilled(this.value)
//         } else if (this.status === 'reject') {
//             onRejected(this.reason)
//         } else if (this.status === 'pending') { // 异步未完成，先存起来回调函数，等待调用。
//             this.onFulfilledCallback = onFulfilled
//             this.onRejectedCallback = onRejected
//         }
//     }
// }
// // 测试一下
// let promise = new MyPromise((res, rej) => {
//     setTimeout(() => {
//         res('成功')
//     }, 1000)
// })
// promise.then(console.log)
// // 一秒后打印成功，证明已经可以处理异步操作了。
// // 如果再次执行.then, 第一次的结果就不会打印了
// promise.then((value) =>{
//     console.log('第二次')
//     console.log(value)
// })
// 为了实现then的多次调用还需要改进一下
// class MyPromise {
//     status = 'pending'
//     value = undefined
//     reason = undefined
//     onFulfilledCallback = []    // 改为数组，循环调用
//     onRejectedCallback = []
//     constructor(executor) {
//         executor(this.resolve, this.reject)
//     }
//     resolve = (value) => {
//         if (this.status === 'pending') {
//             this.status = 'fulfilled'
//             this.value = value
//             this.onFulfilledCallback.forEach(v => v(value))

//         }
//     }
//     reject = (reason) => {
//         if (this.status === 'pending') {
//             this.status = 'reject'
//             this.reason = reason
//             this.onRejectedCallback.forEach(v => v(value))
//         }
//     }
//     then(onFulfilled, onRejected) {
//         if (this.status === 'fulfilled') {
//             onFulfilled(this.value)
//         } else if (this.status === 'reject') {
//             onRejected(this.reason)
//         } else if (this.status === 'pending') {
//             this.onFulfilledCallback.push(onFulfilled)
//             this.onRejectedCallback.push(onRejected)
//         }
//     }
// }
// let promise = new MyPromise((res, rej) => {
//     setTimeout(() => {
//         res('成功')
//     }, 1000)
// })
// promise.then(console.log)
// promise.then((value) =>{
//     console.log('第二次')
//     console.log(value)
// })
// 现在已经实现了then的多次调用

// 链式调用，刚才的写法无法链式调用。想要实现链式调用，必须.then方法有一个返回值也是Promise，就可以实现链式调用了，修改一下.then方法。
// class MyPromise {
//     status = 'pending'
//     value = undefined
//     reason = undefined
//     onFulfilledCallback = []    // 改为数组，循环调用
//     onRejectedCallback = []
//     constructor(executor) {
//         executor(this.resolve, this.reject)
//     }
//     resolve = (value) => {
//         if (this.status === 'pending') {
//             this.status = 'fulfilled'
//             this.value = value
//             this.onFulfilledCallback.forEach(v => v(value))
//         }
//     }
//     reject = (reason) => {
//         if (this.status === 'pending') {
//             this.status = 'reject'
//             this.reason = reason
//             this.onRejectedCallback.forEach(v => v(value))
//         }
//     }
//     then(onFulfilled, onRejected) {
//         const promise2 = new MyPromise((resolve, reject) => {
//             if (this.status === 'fulfilled') {
//                 let x = onFulfilled(this.value) // 执行第一个promise的回调函数，获取此回调函数的返回值
//                 if (x instanceof MyPromise) {   // 回调函数返回一个Promise，需要链式调用
//                     // x.then(val => resolve(val), reason => reject(reason))     // 返回的MyPromise执行完毕后，执行回调，传出参数。
//                     x.then(resolve, reject) // 简化
//                 } else {
//                     resolve(x)  // 没有返回MyPromise，直接resolve
//                 }
//             } else if (this.status === 'reject') {
//                 onRejected(this.reason)
//             } else if (this.status === 'pending') {
//                 this.onFulfilledCallback.push(onFulfilled)
//                 this.onRejectedCallback.push(onRejected)
//             }
//         })
//         return promise2
//     }
// }
// const promise = new MyPromise((res) => {
//     res('1')
// })
// promise.then(val => {
//     console.log(val, 'success')
//     return new MyPromise((res) => {
//         res('2')
//     })
// }).then(val => {
//     console.log(val, 'success')
// })

// 使用原生Promise如果then方法返回的是自己的Promise对象，则会发生循环调用，这个时候程序会报错。TypeError: Chaining cycle detected for promise #<Promise>，检测到promise循环调用
// const promise = new Promise(res => {
//     res('1')
// })
// let a = promise.then(val => {
//     console.log(val)
//     return a
// })
// 改造一下MyPromise,并用queueMicrotask创建微任务
// class MyPromise {
//     status = 'pending'
//     value = undefined
//     reason = undefined
//     onFulfilledCallback = []
//     onRejectedCallback = []
//     constructor(executor) {
//         executor(this.resolve, this.reject)
//     }
//     resolve = (value) => {
//         if (this.status === 'pending') {
//             this.status = 'fulfilled'
//             this.value = value
//             this.onFulfilledCallback.forEach(v => v(value))
//         }
//     }
//     reject = (reason) => {
//         if (this.status === 'pending') {
//             this.status = 'reject'
//             this.reason = reason
//             this.onRejectedCallback.forEach(v => v(value))
//         }
//     }
//     then(onFulfilled, onRejected) {
//         const promise2 = new MyPromise((resolve, reject) => {
//             if (this.status === 'fulfilled') {
//                 queueMicrotask(() => {
//                     const x = onFulfilled(this.value)
//                     resolvePromise(promise2, x, resolve, reject)    // 封装一个方法集中处理
//                 })
//             } else if (this.status === 'reject') {
//                 onRejected(this.reason)
//             } else if (this.status === 'pending') {
//                 this.onFulfilledCallback.push(onFulfilled)
//                 this.onRejectedCallback.push(onRejected)
//             }
//         })
//         return promise2
//     }
// }
function resolvePromise(promise2, x, resolve, reject) {
    if (x === promise2) {
        return reject('Chaining cycle detected for promise #<Promise>')
    }
    if (x instanceof MyPromise) {
        x.then(resolve, reject)
    } else {
        resolve(x)
    }
}
// const promise = new MyPromise(res => {
//     res('1')
// })
// const a = promise.then(val => {
//     console.log(val)
//     return a
// })
// 执行后抛出异常，正是我们要的结果，继续下一步
// 使用try catch来捕获异常，如果有代码错误，Promise的状态要变为失败reject
// class MyPromise {
//     status = 'pending'
//     value = undefined
//     reason = undefined
//     onFulfilledCallback = []
//     onRejectedCallback = []
//     constructor(executor) {
//         try {
//             executor(this.resolve, this.reject)
//         } catch(err) {
//             this.reject(err)
//         }
//     }
//     resolve = (value) => {
//         if (this.status === 'pending') {
//             this.status = 'fulfilled'
//             this.value = value
//             this.onFulfilledCallback.forEach(v => v(value))
//         }
//     }
//     reject = (reason) => {
//         if (this.status === 'pending') {
//             this.status = 'reject'
//             this.reason = reason
//             this.onRejectedCallback.forEach(v => v(value))
//         }
//     }
//     then(onFulfilled, onRejected) {
//         const promise2 = new MyPromise((resolve, reject) => {
//             if (this.status === 'fulfilled') {
//                 queueMicrotask(() => {
//                     try {
//                         const x = onFulfilled(this.value)
//                         resolvePromise(promise2, x, resolve, reject)
//                     } catch(err) {
//                         onRejected(err)
//                     }
//                 })
//             } else if (this.status === 'reject') {
//                 onRejected(this.reason)
//             } else if (this.status === 'pending') {
//                 this.onFulfilledCallback.push(onFulfilled)
//                 this.onRejectedCallback.push(onRejected)
//             }
//         })
//         return promise2
//     }
// }
// // 以下两种异常使用方式都可以捕获到。
// let promise = new MyPromise()
// promise.then(console.log, console.log)

// let promise = new MyPromise((res) =>{
//     res('11')
// })
// promise.then('', console.log)

// 对reject和pending状态进行改造：增加异步状态下的链式调用、增加回调函数执行结果的判断、增加识别 Promise 是否返回自己、增加错误捕获
// then的参数可选，例如promise.then().then().then(console.log)
// class MyPromise {
//     status = 'pending'
//     value = undefined
//     reason = undefined
//     onFulfilledCallback = []
//     onRejectedCallback = []
//     constructor(executor) {
//         try {
//             executor(this.resolve, this.reject)
//         } catch(err) {
//             this.reject(err)
//         }
//     }
//     resolve = (value) => {
//         if (this.status === 'pending') {
//             this.status = 'fulfilled'
//             this.value = value
//             this.onFulfilledCallback.forEach(v => v(value))
//         }
//     }
//     reject = (reason) => {
//         if (this.status === 'pending') {
//             this.status = 'reject'
//             this.reason = reason
//             this.onRejectedCallback.forEach(v => v(value))
//         }
//     }
//     then(onFulfilled, onRejected) {
//         onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : a => a
//         onRejected = typeof onRejected === 'function' ? onRejected : a => a
//         const promise2 = new MyPromise((resolve, reject) => {
//             if (this.status === 'fulfilled') {
//                 queueMicrotask(() => {
//                     try {
//                         const x = onFulfilled(this.value)
//                         resolvePromise(promise2, x, resolve, reject)
//                     } catch(err) {
//                         onRejected(err)
//                     }
//                 })
//             } else if (this.status === 'reject') {
//                 queueMicrotask(() => {
//                     try {
//                         const x = onRejected(this.reason)
//                         resolvePromise(promise2, x, resolve, reject)
//                     } catch(err) {
//                         reject(err)
//                     }
//                 })
//             } else if (this.status === 'pending') {     // 不知道状态将要变成什么，先存起来处理函数，等到状态确定再去执行。
//                 this.onFulfilledCallback.push(queueMicrotask(() =>{
//                     try {
//                         const x = onFulfilled(this.value)
//                         resolvePromise(promise2, x, resolve, reject)
//                     } catch(err) {
//                         onRejected(err)
//                     }
//                 }))
//                 this.onRejectedCallback.push(queueMicrotask(() => {
//                     try {
//                         const x = onRejected(this.reason)
//                         resolvePromise(promise2, x, resolve, reject)
//                     } catch(err) {
//                         reject(err)
//                     }
//                 }))
//             }
//         })
//         return promise2
//     }
// }
// 到此为止一个Promise基本上就快完成了，回到上面的面试题的写法，用Promise.resolve()来返回一个Promise对象
// MyPromise.resolve().then(() => {
//     console.log(0);
//     return MyPromise.resolve(4);
// }).then((res) => {
//     console.log(res)
// })
// 竟然报错了😂，所以还需要给MyPromise增加static静态方法，整理代码(我都快要写吐了)
export class MyPromise {
    status = 'pending'
    value = undefined
    reason = undefined
    onFulfilledCallback = []
    onRejectedCallback = []
    constructor(executor) {
        try {
            executor(this.resolve, this.reject)
        } catch(err) {
            this.reject(err)
        }
    }
    resolve = (value) => {
        if (this.status === 'pending') {
            this.status = 'fulfilled'
            this.value = value
            while (this.onFulfilledCallback.length) {
                this.onFulfilledCallback.shift()(value)
            }
        }
    }
    reject = (reason) => {
        if (this.status === 'pending') {
            this.status = 'reject'
            this.reason = reason
            while (this.onRejectedCallback.length) {
                this.onRejectedCallback.shift()(value)
            }
        }
    }
    then(onFulfilled, onRejected) {
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : a => a
        onRejected = typeof onRejected === 'function' ? onRejected : a => a
        const promise2 = new MyPromise((resolve, reject) => {
            const fulfilledMicrotask = () => {
                queueMicrotask(() => {
                    try {
                        const x = onFulfilled(this.value)
                        resolvePromise(promise2, x, resolve, reject)
                    } catch(err) {
                        onRejected(err)
                    }
                })
            }
            const rejectedMicrotask = () => {
                queueMicrotask(() => {
                    try {
                        const x = onRejected(this.reason)
                        resolvePromise(promise2, x, resolve, reject)
                    } catch(err) {
                        reject(err)
                    }
                })
            }
            if (this.status === 'fulfilled') {
                fulfilledMicrotask()
            } else if (this.status === 'reject') {
                rejectedMicrotask()
            } else if (this.status === 'pending') {
                this.onFulfilledCallback.push(fulfilledMicrotask)
                this.onRejectedCallback.push(rejectedMicrotask)
            }
        })
        return promise2
    }
    static resolve(val) {
        if (val instanceof MyPromise) { // 传入Promise对象，直接返回
            return val
        }
        return new MyPromise(res => {
            res(val)
        })
    }
    static reject(rea) {
        return new MyPromise((res, rej) => {
            rej(rea)
        })
    }
}
// 继续看面试题
MyPromise.resolve().then(() => {
    console.log(0);
    return MyPromise.resolve(4);
}).then((res) => {
    console.log(res)
})
MyPromise.resolve().then(() => {
    console.log(1);
}).then(() => {
    console.log(2);
}).then(() => {
    console.log(3);
}).then(() => {
    console.log(5);
}).then(() =>{
    console.log(6);
})
// 打印结果为0 1 2 4 3 5 6， 这不是和我们分析的一样吗🤣，为什么原生Promise执行出来就是0 1 2 3 4 5 6 (什么?MyPromise还没结束?)
// 看一下resolvePromise
// function resolvePromise(promise2, x, resolve, reject) {
//     if (x === promise2) {
//         return reject('Chaining cycle detected for promise #<Promise>')
//     }
//     if (x instanceof MyPromise) {
//         x.then(resolve, reject)  // 这里直接执行了.then完成状态转换，本应该在下一次的微任务队列里面
//     } else {
//         resolve(x)
//     }
// }
// 其实分析执行过程并不难发现，在return MyPromise.resolve(4)的时候，x被传入resolvePromise，并被判断为MyPromise对象，然后直接执行x.then方法完成状态转换
// 原生Promise在Promise.resolve(4)的时候，js引擎会创建一个微任务
// 所以在resolvePromise方法里面创建一个微任务可以解决此问题
function resolvePromise(promise2, x, resolve, reject) {
    if (x === promise2) {
        return reject('Chaining cycle detected for promise #<Promise>')
    }
    if (x instanceof MyPromise) {
        queueMicrotask(() => {
            x.then(resolve, reject)
        })
    } else {
        resolve(x)
    }
}
// 至此为止，这道面试题的整个运行过程已经清晰明了。我也该收拾收拾下班了😁